package com.billy.ohos.swipe;

import com.billy.ohos.swipe.internal.LogUtil;
import com.billy.ohos.swipe.internal.SwipeHelper;
import com.billy.ohos.swipe.internal.ViewCompat;
import com.ryan.ohos.extension.EstimateHelper;
import com.ryan.ohos.extension.event.DispatchHelper;
import com.ryan.ohos.extension.event.impl.ViewGroupHelper;
import com.ryan.ohos.extension.event.interfaces.ComponentParentHack;
import com.ryan.ohos.extension.event.interfaces.ViewGroup;
import com.ryan.ohos.extension.nested.*;
import com.ryan.ohos.extension.scroll.ScrollingView;
import com.ryan.ohos.extension.util.AttrUtils;
import ohos.agp.components.AttrSet;
import ohos.agp.components.Component;
import ohos.agp.components.ComponentContainer;
import ohos.agp.components.DirectionalLayout;
import ohos.agp.render.Canvas;
import ohos.app.Context;
import ohos.multimodalinput.event.TouchEvent;

import java.util.*;

import static com.billy.ohos.swipe.SwipeConsumer.*;
import static com.ryan.ohos.extension.EstimateHelper.getChildMeasureSpec;
import static com.ryan.ohos.extension.EstimateHelper.resolveSizeAndState;
import static java.lang.Math.max;


/**
 * a wrapper to wrap the content view, handle motion events to do swipe business by {@link SwipeHelper} and {@linkSwipeConsumer}
 *
 * @author billy.qi
 */
public class SmartSwipeWrapper extends DirectionalLayout implements ViewGroup, Component.TouchEventListener,
        Component.DrawTask, Component.BindStateChangedListener, Component.EstimateSizeListener,
        ComponentContainer.ArrangeListener, NestedScrollingChild, NestedScrollingParent, ScrollingView, ComponentParentHack {
    private ViewGroupHelper viewGroupHelper;
    private NestedScrollingChildHelper mChildHelper;
    private NestedScrollingParentHelper mParentHelper;
    protected SwipeHelper mHelper;
    protected Component mContentView;
    protected final List<SwipeHelper> mHelpers = new LinkedList<>();
    protected final List<SwipeConsumer> mConsumers = new LinkedList<>();
    protected boolean mInflateFromXml;
    protected boolean mNestedInProgress = false;
    protected boolean mIsNestedScrollingEnabled = true;
//    private ComponentContainer.LayoutConfig params;
    private int direction;
//    private float xDistance, yDistance;
//    private float xLast;
//    private float yLast;
    private int scrollY;
    private int scrollX;

    public SmartSwipeWrapper(Context context) {
        this(context, null, "");
    }

    public SmartSwipeWrapper(Context context, AttrSet attrs) {
        this(context, attrs, "");
    }

    public SmartSwipeWrapper(Context context, AttrSet attrs, String defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

//    @TargetApi(Build.VERSION_CODES.LOLLIPOP)
//    public SmartSwipeWrapper(Context context, AttrSet attrs, int defStyleAttr, int defStyleRes) {
//        super(context, attrs, defStyleAttr, defStyleRes);
//        init();
//    }

    protected void init() {
        viewGroupHelper = new ViewGroupHelper(this);
        mChildHelper = new NestedScrollingChildHelper(this);
        this.mParentHelper = new NestedScrollingParentHelper(this);
        addDrawTask(this);
        setArrangeListener(this);
        setEstimateSizeListener(this);
        setTouchEventListener(this);
        setBindStateChangedListener(this);
    }


    @Override
    public void requestDisallowInterceptTouchEvent(boolean b) {
        LogUtil.loge("wangli1111", " onTouchEvent 55555555 disallowIntercept" + b);
        viewGroupHelper.requestDisallowInterceptTouchEvent(b);
    }

    @Override
    public boolean onInterceptTouchEvent(TouchEvent touchEvent) {
        LogUtil.loge("onTouchEvent", "onInterceptTouchEvent 99   mNestedInProgress  " + mNestedInProgress);
        if (!mNestedInProgress) {
            if (mHelper != null) {
                return mHelper.shouldInterceptTouchEvent(touchEvent);
            } else {
                LogUtil.loge("onInterceptTouchEvent", " onInterceptTouchEvent  101");
                for (SwipeHelper helper : mHelpers) {
                    if (helper.shouldInterceptTouchEvent(touchEvent)) {
                        LogUtil.loge("onInterceptTouchEvent", " onInterceptTouchEvent  104");
                        mHelper = helper;
                        return true;
                    }
                }
            }
        }

        LogUtil.loge("onInterceptTouchEvent", " onInterceptTouchEvent  110");
        return false;
    }

    @Override
    public boolean dispatchTouchEvent(TouchEvent touchEvent) {
        LogUtil.loge("dispatchTouchEvent", "dispatchTouchEvent 116");
        if (touchEvent.getAction() == TouchEvent.PRIMARY_POINT_DOWN) {
            LogUtil.loge("dispatchTouchEvent", "dispatchTouchEvent 118");
            mHelper = null;
        }
        LogUtil.loge("dispatchTouchEvent", "dispatchTouchEvent 120");
        return viewGroupHelper.dispatchTouchEvent(touchEvent);
    }

    @Override
    public boolean onTouchEvent(TouchEvent touchEvent) {
        LogUtil.loge("onTouchEvent", "onTouchEvent 135   mNestedInProgress  " + mNestedInProgress);
        if (!mNestedInProgress) {
            if (mHelper != null) {
                mHelper.processTouchEvent(touchEvent, this);
            } else {
                LogUtil.loge("onTouchEvent", "onTouchEvent 140");
                for (SwipeHelper helper : mHelpers) {
                    LogUtil.loge("onTouchEvent", "onTouchEvent 144");
                    helper.processTouchEvent(touchEvent, this);
                    if (helper.getDragState() == SwipeHelper.STATE_DRAGGING) {
                        mHelper = helper;
                        return true;
                    }
                }
            }
            LogUtil.loge("onTouchEvent", "onTouchEvent 150");
            return true;
        } else {
            LogUtil.loge("onTouchEvent", "onTouchEvent 153");
            return false;
        }
    }


    @Override
    public boolean onTouchEvent(Component component, TouchEvent touchEvent) {
            return DispatchHelper.dispatch(component, touchEvent);
    }

    @Override
    public boolean isConsumed() {
        return viewGroupHelper.isConsumed();
    }





/*
    TODO 无对应
    @Override
    protected void dispatchDraw(Canvas canvas) {
        super.dispatchDraw(canvas);
        for (SwipeConsumer consumer : mConsumers) {
            if (consumer != null) {
                consumer.dispatchDraw(canvas);
            }
        }
    }*/

    //todo A侧没有用到这个方法，就先去掉
   /* public void drawChild(Canvas canvas, Component child) {
        drawChild(canvas, child, getDrawingTime());
    }*/


    @Override
    public void onDraw(Component component, Canvas canvas) {
        ComponentContainer container = (ComponentContainer) component;
        int childCount = container.getChildCount();
        for (int i = 0; i < childCount; i++) {
            for (SwipeConsumer consumer : mConsumers) {
                if (consumer != null) {
                    consumer.dispatchDraw(canvas);
                }
            }
        }


        computeScroll();
    }

    private final ArrayList<Component> mMatchParentChildren = new ArrayList<>(1);

    @Override
    public boolean onEstimateSize(int widthMeasureSpec, int heightMeasureSpec) {
        int count = getChildCount();
        final boolean measureMatchParentChildren =
                EstimateSpec.getMode(widthMeasureSpec) != EstimateSpec.PRECISE ||
                        EstimateSpec.getMode(heightMeasureSpec) != EstimateSpec.PRECISE;
        mMatchParentChildren.clear();

        int maxHeight = 0;
        int maxWidth = 0;
        int childState = 0;

        for (int i = 0; i < count; i++) {
            final Component child = getComponentAt(i);
            final ComponentContainer.LayoutConfig lp = child.getLayoutConfig();
            final int childWidthMeasureSpec = getChildMeasureSpec(widthMeasureSpec, 0, lp.width);
            final int childHeightMeasureSpec = getChildMeasureSpec(heightMeasureSpec, 0, lp.height);
            child.estimateSize(childWidthMeasureSpec, childHeightMeasureSpec);
            maxWidth = Math.max(maxWidth, child.getEstimatedWidth());
            maxHeight = Math.max(maxHeight, child.getEstimatedHeight());
//            childState = combineMeasuredStates(childState, child.getMeasuredState());

            childState = childState | getMeasuredState(child);
            if (measureMatchParentChildren) {
                if (lp.width == LayoutParams.MATCH_PARENT ||
                        lp.height == LayoutParams.MATCH_PARENT) {
                    mMatchParentChildren.add(child);
                }
            }
        }

        // Check against our minimum height and width
        maxHeight = Math.max(maxHeight, getSuggestedMinimumHeight(this));
        maxWidth = Math.max(maxWidth, getSuggestedMinimumWidth(this));
        setEstimatedSize(resolveSizeAndState(maxWidth, widthMeasureSpec),
                resolveSizeAndState(maxHeight, heightMeasureSpec));
        count = mMatchParentChildren.size();
        initCount(count,widthMeasureSpec,heightMeasureSpec);
        for (SwipeConsumer consumer : mConsumers) {
            if (consumer != null) {
                consumer.onMeasure(widthMeasureSpec, heightMeasureSpec);
                // consumer.onMeasure(this.getEstimatedWidth(), this.getEstimatedHeight());
            }
        }
        return true;
    }

    private void initCount(int count, int widthMeasureSpec, int heightMeasureSpec) {
        if (count > 1) {
            for (int i = 0; i < count; i++) {
                final Component child = mMatchParentChildren.get(i);
                final ComponentContainer.LayoutConfig lp = child.getLayoutConfig();

                final int childWidthMeasureSpec;
                if (lp.width == LayoutParams.MATCH_PARENT) {
                    final int width = Math.max(0, getEstimatedWidth());
                    childWidthMeasureSpec = EstimateHelper.makeEstimateSpec(width, EstimateSpec.PRECISE);
                } else {
                    childWidthMeasureSpec = EstimateHelper.getChildMeasureSpec(widthMeasureSpec, 0, lp.width);
                }

                final int childHeightMeasureSpec;
                if (lp.height == LayoutParams.MATCH_PARENT) {
                    final int height = Math.max(0, getEstimatedHeight());
                    childHeightMeasureSpec = EstimateSpec.getSizeWithMode(height, EstimateSpec.PRECISE);
                } else {
                    childHeightMeasureSpec = EstimateHelper.getChildMeasureSpec(heightMeasureSpec, 0, lp.height);
                }

                child.estimateSize(childWidthMeasureSpec, childHeightMeasureSpec);
            }
        }
    }

    /*onEstimateSize  的api ========start*/

    protected int getSuggestedMinimumHeight(Component view) {
        return (view.getBackgroundElement() == null) ? view.getMinHeight() : max(view.getMinHeight(), getMinimumHeight());

    }

    protected int getSuggestedMinimumWidth(Component view) {
        return (view.getBackgroundElement() == null) ? view.getMinWidth() : max(view.getMinWidth(), getMinimumWidth());
    }

    public int getMinimumWidth() {
        final int intrinsicWidth = -1;
        return intrinsicWidth > 0 ? intrinsicWidth : 0;
    }

    public int getMinimumHeight() {
        final int intrinsicHeight = -1;
        return intrinsicHeight > 0 ? intrinsicHeight : 0;
    }


    public static final int MEASURED_HEIGHT_STATE_SHIFT = 16;

    public int getMeasuredState(Component child) {
        return (child.getEstimatedWidth() & EstimateSpec.ESTIMATED_STATE_BIT_MASK)
                | ((child.getEstimatedHeight() >> MEASURED_HEIGHT_STATE_SHIFT)
                & (EstimateSpec.ESTIMATED_STATE_BIT_MASK >> MEASURED_HEIGHT_STATE_SHIFT));
    }

    /*onEstimateSize  的api ========end */

    @Override
    public boolean onArrange(int left, int top, int right, int bottom) {


        boolean layoutByConsumer = false;
        for (int i = 0; i < getChildCount(); i++) {
            Component child = getComponentAt(i);
            LayoutParams lp = (LayoutParams) child.getLayoutConfig();
            LogUtil.loge("onArrange","lp=====" + lp.gravity);
            if (lp.gravity == DIRECTION_NONE) {
                LogUtil.loge("onArrange","DIRECTION_NONE");
                child.arrange(0, 0, child.getEstimatedWidth(), child.getEstimatedHeight());
            }else {
                child.arrange(-child.getEstimatedWidth(), -child.getEstimatedHeight(),child.getEstimatedWidth(),child.getEstimatedHeight());
            }
        }

//        LogUtil.loge("onArrage444","right =====" +  right   + "   bottom  ======"  + bottom);

        if (mHelper != null) {
            layoutByConsumer = mHelper.getSwipeConsumer().onLayout(true, left, top, right, bottom);
        } else {
            for (SwipeConsumer consumer : mConsumers) {
                if (consumer != null && consumer.onLayout(true, left, top, right, bottom)) {
                    layoutByConsumer = true;
                }
            }
        }
        if (!layoutByConsumer) {
            if (mContentView != null) {
                mContentView.arrange(0, 0, mContentView.getEstimatedWidth(), mContentView.getEstimatedHeight());
            }
        }
        return true;
    }

    //todo 暂无替换方法
    // @Override
    public void onFinishInflate() {
        // super.onFinishInflate();
        //compat for xml usage
        mInflateFromXml = true;
        int childCount = getChildCount();
        LogUtil.loge("isInflateFromXml", "ohos111111111" + (mContentView == null));
        if (childCount > 0 && mContentView == null) {
            for (int i = 0; i < childCount; i++) {
                LogUtil.loge("isInflateFromXml", "ohos222222222childCount   " + childCount + getComponentAt(i).getClass().getSimpleName());
                Component child = getComponentAt(i);
                ComponentContainer.LayoutConfig layoutParams = child.getLayoutConfig();
                if (layoutParams instanceof LayoutParams) {
                    LogUtil.loge("isInflateFromXml", "ohos333333333");
                    final int gravity = ((LayoutParams) layoutParams).gravity;
                    if (gravity == LayoutParams.UNSPECIFIED_GRAVITY) {
                        LogUtil.loge("isInflateFromXml", "ohos444444444");
                        setContentView(child);
                        break;
                    }
                }
            }
        }
    }

    public void computeScroll() {
        if (!mHelpers.isEmpty()) {
            boolean shouldContinue = false;
            for (SwipeHelper helper : mHelpers) {
                if (helper.continueSettling()) {
                    shouldContinue = true;
                }
            }
            if (shouldContinue) {
                ViewCompat.postInvalidateOnAnimation(this);
            }
        }
    }

    public <T extends SwipeConsumer> T addConsumer(T consumer) {
        if (consumer != null) {
            this.mConsumers.add(consumer);
            SwipeHelper helper = consumer.getSwipeHelper();
            if (helper == null) {
                helper = SwipeHelper.create(this, consumer.getSensitivity(), consumer, consumer.getInterpolator());
            }
            consumer.onAttachToWrapper(this, helper);
            mHelpers.add(helper);
        }
        return consumer;
    }

    public SmartSwipeWrapper removeAllConsumers() {
        Iterator<SwipeConsumer> iterator = mConsumers.iterator();
        while (iterator.hasNext()) {
            SwipeConsumer consumer = iterator.next();
            iterator.remove();
            if (consumer != null) {
                consumer.onDetachFromWrapper();
                SwipeHelper swipeHelper = consumer.getSwipeHelper();
                mHelpers.remove(swipeHelper);
                if (mHelper == swipeHelper) {
                    mHelper = null;
                }
            }
        }
        return this;
    }

    public SmartSwipeWrapper removeConsumer(SwipeConsumer consumer) {
        boolean removed = mConsumers.remove(consumer);
        if (removed) {
            consumer.onDetachFromWrapper();
            SwipeHelper swipeHelper = consumer.getSwipeHelper();
            mHelpers.remove(swipeHelper);
            if (mHelper == swipeHelper) {
                mHelper = null;
            }
        }
        return this;
    }

    public SwipeConsumer getConsumerByType(Class<? extends SwipeConsumer> clazz) {
        for (SwipeConsumer consumer : mConsumers) {
            if (consumer != null && consumer.getClass() == clazz) {
                return consumer;
            }
        }
        return null;
    }

    public void setContentView(Component contentView) {
        if (contentView == null || this.mContentView == contentView) {
            return;
        }
        this.mContentView = contentView;
        if (contentView.getComponentParent() == null) {
            addComponent(contentView);
        }
    }

    public Component getContentView() {
        return mContentView;
    }

    public List<SwipeConsumer> getAllConsumers() {
        return mConsumers;
    }

    public SmartSwipeWrapper enableDirection(int direction) {
        return enableDirection(direction, true);
    }

    public SmartSwipeWrapper enableDirection(int direction, boolean enable) {
        for (SwipeConsumer consumer : mConsumers) {
            consumer.enableDirection(direction, enable);
        }
        return this;
    }

    public boolean isInflateFromXml() {
        return mInflateFromXml;
    }

    public void consumeInflateFromXml() {
        this.mInflateFromXml = false;
    }

    //@Override todo 暂无对应方法
    public boolean shouldDelayChildPressedState() {
        return false;
    }

    //@Override todo 暂无对应方法
    public ComponentContainer.LayoutConfig generateDefaultLayoutParams() {
        return new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
    }


    @Override
    public ComponentContainer.LayoutConfig createLayoutConfig(Context context, AttrSet attrSet) {
        return new LayoutParams(context, attrSet);
    }

    public LayoutParams generateLayoutParams(AttrSet attrs) {
        return new LayoutParams(getContext(), attrs);
    }

    public ComponentContainer.LayoutConfig generateLayoutParams(ComponentContainer.LayoutConfig lp) {
        if (lp instanceof LayoutParams) {
            return new LayoutParams((LayoutParams) lp);
        }
        return new LayoutParams(lp);
    }

    @Override
    public ComponentContainer.LayoutConfig verifyLayoutConfig(ComponentContainer.LayoutConfig config) {
        if (config instanceof LayoutParams) {
            return config;
        }
        return new LayoutParams(config);
    }


    @Override
    public ComponentContainer getContainer() {
        return this;
    }

    @Override
    public int getScrollY() {
        return scrollY;
    }

    @Override
    public int getScrollX() {
        return scrollX;
    }

    @Override
    public int getDirection() {
        return getOrientation() + 1;
    }

    @Override
    public void scrollByInternal(int deltaX, int deltaY) {
        // 需要自行计算scrollX、scrollY，因为有时候getScrollValue函数返回有异常
        if (getDirection() == NestedScrollingHelper.SCROLL_AXIS_VERTICAL) {
            scrollY += deltaY;
            if (scrollY < 0) {
                scrollY = 0;
            }
        } else {
            scrollX += deltaX;
            if (scrollX < 0) {
                scrollX = 0;
            }
        }
        scrollTo(scrollX, scrollY);

        if (scrollY > getScrollValue(VERTICAL)) {
            scrollY = getScrollValue(VERTICAL);
        }

        if (scrollX > getScrollValue(HORIZONTAL)) {
            scrollX = getScrollValue(HORIZONTAL);
        }
    }

    @Override
    public boolean disallowInterceptWhenMoving() {
        return true;
    }

    public void setOnDirectionLisenter(OnDirectionLisenter lisenter) {
        this.lisenter = lisenter;
    }

    private OnDirectionLisenter lisenter;
    private ComponentContainer parent;

    /**
     * getLisenter
     *
     * @return OnDirectionLisenter
     */
    public OnDirectionLisenter getLisenter() {
        return lisenter;
    }

    @Override
    public ComponentContainer getComponentParentHack() {
        return parent;
    }

    @Override
    public void setComponentParent(ComponentContainer parent) {
        this.parent = parent;
    }

    public interface OnDirectionLisenter {
        void onHorizental(float xLast, float curX);

        void onVeltical(float yLast, float curY);

        void close();
    }


    public static class LayoutParams extends ComponentContainer.LayoutConfig {
        /**
         * Value for {@link #gravity} indicating that a gravity has not been
         * explicitly specified.
         */
        public static final int UNSPECIFIED_GRAVITY = 0;

        /**
         * The gravity to apply with the View to which these layout parameters
         * are associated.
         */
        public int gravity = UNSPECIFIED_GRAVITY;

        public LayoutParams(Context c, AttrSet attrs) {
            super(c, attrs);

//            final TypedArray a = c.obtainStyledAttributes(attrs, R.styleable.SmartSwipeWrapper_Layout);
            String gravityStr = AttrUtils.getString(attrs, "swipe_gravity", "none");
            gravity = getGravity(gravityStr.replaceAll(" ", ""));
            LogUtil.loge("wangli===", "gravityStr  ==== " + gravityStr);
//            a.recycle();
        }

        private int getGravity(String gravityStr) {
            switch (gravityStr) {
                case "left":
                    return DIRECTION_LEFT;
                case "right":
                    return DIRECTION_RIGHT;
                case "top":
                    return DIRECTION_TOP;
                case "bottom":
                    return DIRECTION_BOTTOM;
                case "left|right":
                case "right|left":
                    return DIRECTION_HORIZONTAL;
                case "top|bottom":
                case "bottom|top":
                    return DIRECTION_VERTICAL;
                case "all":
                    return DIRECTION_ALL;
                default:
                    return DIRECTION_NONE;
            }
        }

        public LayoutParams(int width, int height) {
            super(width, height);
        }

        /**
         * Creates a new set of layout parameters with the specified width, height
         * and weight.
         *
         * @param width   the width, either {@link #MATCH_PARENT},
         *                {@link #MATCH_CONTENT} or a fixed size in pixels
         * @param height  the height, either {@link #MATCH_PARENT},
         *                {@link #MATCH_CONTENT} or a fixed size in pixels
         * @param gravity the gravity
         * @see
         */
        public LayoutParams(int width, int height, int gravity) {
            super(width, height);
            this.gravity = gravity;
        }

        public LayoutParams(ComponentContainer.LayoutConfig source) {
            super(source);
        }

        //ViewGroup.MarginLayoutParams todo 没有对应
       /* public LayoutParams(ViewGroup.MarginLayoutParams source) {
            super(source);
        }*/

        /**
         * Copy constructor. Clones the width, height, margin values, and
         * gravity of the source.
         *
         * @param source The layout params to copy from.
         */
        public LayoutParams(LayoutParams source) {
            super(source);
            this.gravity = source.gravity;
        }
    }

    @Override
    public void onComponentBoundToWindow(Component component) {
        setNestedScrollingEnabled(mIsNestedScrollingEnabled);
    }


    @Override
    public void onComponentUnboundFromWindow(Component component) {
//        for (SwipeConsumer consumer : mConsumers) {
//            if (consumer.isAutoCloseOnWrapperDetachedFromWindow()) {
//                consumer.close();
//            }
//        }
    }

    @Override
    public void setNestedScrollingEnabled(boolean enabled) {
        mIsNestedScrollingEnabled = enabled;
       /* if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            super.setNestedScrollingEnabled(enabled);
        }*/
        mChildHelper.setNestedScrollingEnabled(enabled);
    }

    @Override
    public boolean isNestedScrollingEnabled() {
//        return mIsNestedScrollingEnabled;
      /*  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            return super.isNestedScrollingEnabled();
        }
        return false;*/
        return mChildHelper.isNestedScrollingEnabled();
//        return false;
    }


    @Override
    public boolean onStartNestedScroll(Component child, Component target, int nestedScrollAxes, int type) {
        LogUtil.loge("wrapper22222", "onStartNestedScroll  1111111");
        return onStartNestedScroll2(child, target, nestedScrollAxes, type);
    }

    @Override
    public void onNestedScrollAccepted(Component child, Component target, int axes, int type) {
        LogUtil.loge("wrapper22222", "onNestedScrollAccepted  222222222");
        onNestedScrollAccepted2(child, target, axes, type);
    }

    @Override
    public void onStopNestedScroll(Component child, int type) {
        onStopNestedScroll2(child, type);
        LogUtil.loge("wrapper22222", "onStopNestedScroll  55555555" + mNestedInProgress);
    }

    @Override
    public void onNestedPreScroll(Component target, int dx, int dy, int[] consumed, int type) {
        LogUtil.loge("wrapper22222", "onNestedPreScroll  333333333");
        onNestedPreScroll2(target, dx, dy, consumed, type);
    }

    @Override
    public void onNestedScroll(Component target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type, int[] consumed) {
        LogUtil.loge("wrapper22222", "onNestedScroll  44444444444");
        onNestedScroll2(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type, consumed);
    }

    /////////////////////////////////////////
    //
    // support for NestedScrollingParent2 todo 暂时屏蔽
    //
    /////////////////////////////////////////

    public boolean onStartNestedScroll2(Component child, Component target, int axes, int type) {
        boolean vertical = (axes & ViewCompat.SCROLL_AXIS_VERTICAL) != 0;
        boolean horizontal = (axes & ViewCompat.SCROLL_AXIS_HORIZONTAL) != 0;
        for (SwipeConsumer consumer : mConsumers) {
            int direction = consumer.getDirection();
            boolean handle;
            if (direction != DIRECTION_NONE) {
                //only handle the same axes as current swipe direction
                handle = horizontal && (direction == DIRECTION_LEFT || direction == DIRECTION_RIGHT);
                handle = handle || vertical && (direction == DIRECTION_TOP || direction == DIRECTION_BOTTOM);
            } else {
                handle = horizontal && (consumer.isLeftEnable() || consumer.isRightEnable());
                handle = handle || vertical && (consumer.isTopEnable() || consumer.isBottomEnable());
            }
            if (handle) {
                startNestedScroll(axes, type);
                LogUtil.loge("wrapper11111111", "onStartNestedScroll  " + axes);
                return true;
            }
        }
        return false;
    }

    private static final int NESTED_TYPE_INVALID = -1;
    protected int mCurNestedType = NESTED_TYPE_INVALID;
    protected boolean mNestedFlyConsumed;

    public void onNestedScrollAccepted2(Component child, Component target, int axes, int type) {
        mNestedInProgress = true;
        LogUtil.loge("wrapper1111", "onNestedScrollAccepted222222  mNestedInProgress" + mNestedInProgress + child.getClass().getSimpleName());
        mNestedFlyConsumed = false;
        flyToOpen = flyToClose = null;
        mCurNestedType = type;
        helperOnNestedScrollAccepted(child, target, axes, type);
    }

    public void onStopNestedScroll2(Component target, int type) {
        mNestedInProgress = false;
        LogUtil.loge("wrapper1111", "onStopNestedScroll2222222  + mNestedInProgress" + mNestedInProgress + target.getClass().getSimpleName());
        helperOnStopNestedScroll(target, type);
        if (type == mCurNestedType) {
            mCurNestedType = NESTED_TYPE_INVALID;
            if (mHelper != null) {
                mHelper.nestedScrollingRelease();
            }
        }
    }

    @Override
    public boolean onNestedFling(Component target, float velocityX, float velocityY, boolean consumed) {
        return mChildHelper.dispatchNestedFling(velocityX, velocityY, true);
    }

    @Override
    public boolean onNestedPreFling(Component target, float velocityX, float velocityY) {
        return mChildHelper.dispatchNestedPreFling(velocityX, velocityY);
    }

    protected int[] mParentOffsetInWindow = new int[2];

    public void onNestedScroll2(Component target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type, int[] consumed) {
        helperOnNestedScroll(target, dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, type);
        dxUnconsumed += mParentOffsetInWindow[0];
        dyUnconsumed += mParentOffsetInWindow[1];
        if (dxUnconsumed != 0 || dyUnconsumed != 0) {
            if (type == ViewCompat.TYPE_NON_TOUCH) {
                //fling nested scroll has not been consumed
                requestDisallowInterceptTouchEvent(false);
            }
            wrapperNestedScroll(dxUnconsumed, dyUnconsumed, consumed, type);
        }
    }

    public void onNestedPreScroll2(Component target, int dx, int dy, int[] consumed, int type) {
        int consumedX = 0, consumedY = 0;
        boolean helperConsumed = false;
        if (mHelper == null || mHelper.getSwipeConsumer().getProgress() == 0) {
            helperConsumed = true;
            Arrays.fill(consumed, 0);
            helperOnNestedPreScroll(target, dx, dy, consumed, type);
            consumedX += consumed[0];
            consumedY += consumed[1];
        }
        if (mHelper != null && mHelper.getSwipeConsumer().getDirection() != DIRECTION_NONE) {
            Arrays.fill(consumed, 0);
            wrapperNestedScroll(dx - consumedX, dy - consumedY, consumed, type);
            consumedX -= consumed[0];
            consumedY -= consumed[1];
        }
        if (!helperConsumed) {
            Arrays.fill(consumed, 0);
            helperOnNestedPreScroll(target, dx - consumedX, dy - consumedY, consumed, type);
            consumedX += consumed[0];
            consumedY += consumed[1];
        }
        consumed[0] = consumedX;
        consumed[1] = consumedY;
    }


    @Override
    public int getNestedScrollAxes() {
        return mParentHelper.getNestedScrollAxes();
    }

    private Boolean flyToOpen, flyToClose;


    private void wrapperNestedScroll(int dxUnconsumed, int dyUnconsumed, int[] consumed, int type) {
        if (mCurNestedType == NESTED_TYPE_INVALID) {
            //resolve problem: miss a call of: onStartNestedScroll(type = 1) and onNestedScrollAccepted(type=0)
            // time line like this:
            //  onStartNestedScroll(type=0)
            //  onNestedScrollAccepted(type=0)
            //  some onNestedPreScroll/onNestedScroll(type=0)...
            //  onStopNestedScroll(type=0)
            //  some onNestedPreScroll/onNestedScroll(type=1)...
            //  onStopNestedScroll(type=1)
            mCurNestedType = type;
            mNestedFlyConsumed = false;
            flyToOpen = flyToClose = null;
        }
        boolean fly = type == ViewCompat.TYPE_NON_TOUCH;
        if (mHelper != null) {
            initFly(fly,dxUnconsumed,dyUnconsumed,consumed);
        } else {
            for (SwipeHelper helper : mHelpers) {
                if (helper != null) {
                    //try to determined which SwipeHelper will handle this fake drag via nested scroll
                    if (helper.nestedScrollingTrySwipe(-dxUnconsumed, -dyUnconsumed, type == ViewCompat.TYPE_NON_TOUCH)) {
                        mHelper = helper;
                        break;
                    }
                }
            }
        }
    }

    private void initFly(boolean fly, int dxUnconsumed, int dyUnconsumed, int[] consumed) {
        SwipeConsumer consumer = mHelper.getSwipeConsumer();
        float maxProgress = PROGRESS_OPEN + consumer.getOverSwipeFactor();
        if (fly) {
            if (flyToOpen == null) {
                //scroll trending:
                // ↓: y < 0, ↑: y > 0
                // →: x < 0, ←: x > 0
                switch (consumer.getDirection()) {
                    case DIRECTION_TOP:
                        flyToOpen = dyUnconsumed < 0;
                        flyToClose = dyUnconsumed > 0;
                        if (dyUnconsumed == 0) {
                            return;
                        }
                        break;
                    case DIRECTION_BOTTOM:
                        flyToOpen = dyUnconsumed > 0;
                        flyToClose = dyUnconsumed < 0;
                        if (dyUnconsumed == 0) {
                            return;
                        }
                        break;
                    case DIRECTION_LEFT:
                        flyToOpen = dxUnconsumed < 0;
                        flyToClose = dxUnconsumed > 0;
                        if (dxUnconsumed == 0) {
                            return;
                        }
                        break;
                    case DIRECTION_RIGHT:
                        flyToOpen = dxUnconsumed > 0;
                        flyToClose = dxUnconsumed < 0;
                        if (dxUnconsumed == 0) {
                            return;
                        }
                        break;
                    default:
                        flyToOpen = flyToClose = false;
                }
            }
            if (!mNestedFlyConsumed) {
                mHelper.nestedScrollingDrag(-dxUnconsumed, -dyUnconsumed, consumed, true);
                if (flyToOpen && consumer.getProgress() >= maxProgress || flyToClose && consumer.getProgress() <= 0) {
                    mNestedFlyConsumed = true;
                    mHelper.nestedScrollingRelease();
                }
            }
        } else {
            mHelper.nestedScrollingDrag(-dxUnconsumed, -dyUnconsumed, consumed, false);
            if (consumer.getProgress() >= maxProgress || consumer.getProgress() <= 0) {
                mHelper = null;
            }
        }
    }

    protected void helperOnNestedScrollAccepted(Component child, Component target, int axes, int type) {
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//            super.onNestedScrollAccepted(child, target, axes);
//        }
        mParentHelper.onNestedScrollAccepted(child, target, axes, type);
//        onNestedScrollAccepted(child, target, axes, type);
    }

    protected void helperOnNestedPreScroll(Component target, int dx, int dy, int[] consumed, int type) {
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//            super.onNestedPreScroll(target, dx, dy, consumed);
//        }
        mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, null, type);
    }

    protected void helperOnNestedScroll(Component target, int dxConsumed, int dyConsumed, int dxUnconsumed, int dyUnconsumed, int type) {
        dispatchNestedScroll(dxConsumed, dyConsumed, dxUnconsumed, dyUnconsumed, mParentOffsetInWindow, type, null);
    }

    protected void helperOnStopNestedScroll(Component target, int type) {
        mParentHelper.onStopNestedScroll(target, type);
        stopNestedScroll(type);
    }

    @Override
    public boolean startNestedScroll(int axes, int mCurNestedType) {
//        return startNestedScroll2(axes, mCurNestedType);
        return startNestedScroll2(axes, mCurNestedType);
    }


    public boolean startNestedScroll2(int axes, int type) {
//        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
//            return super.startNestedScroll(axes);
//        }
//        return false;

        return mChildHelper.startNestedScroll(axes, type);
//                return false;
    }

    @Override
    public void stopNestedScroll(int type) {
//        stopNestedScroll2(type);
        stopNestedScroll2(type);
    }

    public void stopNestedScroll2(int type) {
        mChildHelper.stopNestedScroll(type);
    }

    @Override
    public boolean hasNestedScrollingParent(int type) {
//        return hasNestedScrollingParent2(type);
        return hasNestedScrollingParent2(type);
    }

    public boolean hasNestedScrollingParent2(int type) {

        return mChildHelper.hasNestedScrollingParent(type);
    }


    @Override
    public boolean dispatchNestedScroll(int dxConsumed, int dyConsumed, int dxUnconsumed,
                                        int dyUnconsumed, int[] offsetInWindow, int type, int[] inits) {
        return dispatchNestedScroll2(dxConsumed, dyConsumed,
                dxUnconsumed, dyUnconsumed, offsetInWindow, type);
//                dxUnconsumed, dyUnconsumed, offsetInWindow, ViewCompat.TYPE_TOUCH);
    }

    public boolean dispatchNestedScroll2(int dxConsumed, int dyConsumed, int dxUnconsumed,
                                         int dyUnconsumed, int[] offsetInWindow, int i4) {
        return mChildHelper.dispatchNestedScroll(dxConsumed, dyConsumed,
                dxUnconsumed, dyUnconsumed, offsetInWindow);
    }

    @Override
    public boolean dispatchNestedPreScroll(int dx, int dy, int[] consumed, int[] offsetInWindow, int type) {
//        return dispatchNestedPreScroll2(dx, dy, consumed, offsetInWindow, type);
        return dispatchNestedPreScroll2(dx, dy, consumed, offsetInWindow, type);
    }

    public boolean dispatchNestedPreScroll2(int dx, int dy, int[] consumed, int[] offsetInWindow, int type0) {
        return mChildHelper.dispatchNestedPreScroll(dx, dy, consumed, offsetInWindow);
    }

    @Override
    public boolean dispatchNestedFling(float velocityX, float velocityY, boolean consumed) {
        return mChildHelper.dispatchNestedFling(velocityX, velocityY, consumed);
    }

    @Override
    public boolean dispatchNestedPreFling(float velocityX, float velocityY) {
        return mChildHelper.dispatchNestedPreFling(velocityX, velocityY);
    }

    private void checkDirection() {
        if (getChildCount() <= 0) {
            return;
        }

        Component child = getComponentAt(0);
        direction = child.getWidth() > child.getHeight() ?
                NestedScrollingHelper.SCROLL_AXIS_HORIZONTAL : NestedScrollingHelper.SCROLL_AXIS_VERTICAL;
    }

    /**
     * getDirections
     *
     * @return int
     */
    public int getDirections(){
        return direction;
    }
}
